/*
 * Copyright (c) Jack魏 2023 - 2023, All Rights Reserved.
 */

package cn.jackwei.yiyi.util;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import lombok.extern.log4j.Log4j2;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * 加解密工具类
 *
 * @author Jack魏
 * @since 2023/11/12 14:12
 */
@Log4j2
public class SecurityUtil {
    /**
     * 默认密码
     */
    public static final String DEFAULT_PASSWORD = "123456";
    /**
     * 随机密码取值
     */
    private static final String KEY = "abcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+-/=[]{}:;'<>?" +
            ".ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     * 扰动次数
     */
    private static final int ENTROPY_NUM = 1000;
    /**
     * BCrypt加密扰动次数
     */
    private static final int LOG2_ROUNDS = 12;

    /**
     * 不能实例化
     */
    private SecurityUtil() {
    }

    /**
     * 根据秘钥给内容加密为Base64
     *
     * @param content 加密内容
     * @param key     秘钥
     * @return 加密后数据
     */
    public static String encryptBase64(String content, String key) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(SymmetricAlgorithm.AES.getValue());
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
            keyGenerator.init(128, secureRandom);
            SecretKey secretKey = keyGenerator.generateKey();
            AES aes = SecureUtil.aes(secretKey.getEncoded());
            return aes.encryptBase64(content);
        } catch (NoSuchAlgorithmException exception) {
            log.error("AES加密失败：", exception);
        }
        return "";
    }

    /**
     * 解密
     *
     * @param encrypt 加密后数据
     * @param key     秘钥
     * @return 解密数据
     */
    public static String decryptStr(String encrypt, String key) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(SymmetricAlgorithm.AES.getValue());
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
            keyGenerator.init(128, secureRandom);
            SecretKey secretKey = keyGenerator.generateKey();
            AES aes = SecureUtil.aes(secretKey.getEncoded());
            return aes.decryptStr(encrypt);
        } catch (NoSuchAlgorithmException exception) {
            log.error("AES解密失败：", exception);
        }
        return "";
    }

    /**
     * 随机指定长度密码
     *
     * @param size 长度
     * @return 密码
     */
    public static String getPassword(int size) {
        // 需要预热一定次数
        for (int i = 0; i < ENTROPY_NUM; i++) {
            RandomUtil.randomString(KEY, size);
        }
        return RandomUtil.randomString(KEY, size);
    }

    /**
     * 获取BCrypt加密密码
     *
     * @param password 明文
     * @return 密码
     */
    public static String getBCryptPassword(String password) {
        return BCrypt.hashpw(password, BCrypt.gensalt(LOG2_ROUNDS));
    }

    /**
     * 验证BCrypt密码
     *
     * @param plaintext 明文
     * @param password  密码
     * @return 是否验证成功
     */
    public static boolean checkBCryptPassword(String plaintext, String password) {
        return BCrypt.checkpw(plaintext, password);
    }
}
